/**
 * Konva.js 相关工具函数
 */

import Konva from "konva";

/**
 * 创建Konva舞台
 * @param {string} containerId - 容器ID
 * @param {number} width - 舞台宽度
 * @param {number} height - 舞台高度
 * @returns {Konva.Stage} Konva舞台实例
 */
export function createStage(containerId, width, height) {
  return new Konva.Stage({
    container: containerId,
    width: width,
    height: height,
  });
}

/**
 * 创建图片图层
 * @returns {Konva.Layer} 图片图层
 */
export function createImageLayer() {
  return new Konva.Layer();
}

/**
 * 创建框选框图层
 * @returns {Konva.Layer} 框选框图层
 */
export function createSelectionLayer() {
  return new Konva.Layer();
}

/**
 * 创建遮罩图层
 * @returns {Konva.Layer} 遮罩图层
 */
export function createMaskLayer() {
  return new Konva.Layer();
}

/**
 * 创建Konva图片对象
 * @param {HTMLImageElement} imageElement - 图片元素
 * @param {Object} bounds - 图片边界 {x, y, width, height}
 * @param {number} rotation - 旋转角度
 * @returns {Konva.Image} Konva图片对象
 */
export function createKonvaImage(imageElement, bounds, rotation = 0) {
  const image = new Konva.Image({
    image: imageElement,
    x: bounds.x,
    y: bounds.y,
    width: bounds.width,
    height: bounds.height,
    rotation: rotation,
  });

  // 如果有旋转，调整旋转中心点
  if (rotation !== 0) {
    image.offsetX(bounds.width / 2);
    image.offsetY(bounds.height / 2);
    image.x(bounds.x + bounds.width / 2);
    image.y(bounds.y + bounds.height / 2);
  }

  return image;
}

/**
 * 创建框选框
 * @param {Object} coord - 坐标对象 {x, y, width, height}
 * @param {string} id - 框选框ID
 * @param {Object} options - 样式选项
 * @returns {Konva.Group} 框选框组
 */
export function createSelectionBox(coord, id, options = {}) {
  const defaultOptions = {
    stroke: "#FFFFFF",
    strokeWidth: 1,
    fill: "rgba(0, 0, 0, 0.3)",
    cornerRadius: 0,
    deleteBtnSize: 24,
    deleteBtnColor: "#FF3B30",
    resizeHandleSize: 16,
    resizeHandleColor: "#FFFFFF",
  };

  const opts = { ...defaultOptions, ...options };

  const group = new Konva.Group({
    x: coord.x,
    y: coord.y,
    width: coord.width,
    height: coord.height,
    draggable: true,
    id: id,
  });

  // 主矩形
  const rect = new Konva.Rect({
    x: 0,
    y: 0,
    width: coord.width,
    height: coord.height,
    stroke: opts.stroke,
    strokeWidth: opts.strokeWidth,
    fill: opts.fill,
    cornerRadius: opts.cornerRadius,
  });

  // 创建四个角的调整控制点
  const handleSize = opts.resizeHandleSize;
  const lineWidth = 3;
  const lineLength = handleSize;

  // 左上角控制点 (L型)
  const topLeftHandle = new Konva.Group({
    draggable: true,
    dragBoundFunc: function (pos) {
      // 获取舞台边界
      const stage = this.getStage();
      const stageBounds = stage
        ? {
            x: 0,
            y: 0,
            width: stage.width(),
            height: stage.height(),
          }
        : { x: 0, y: 0, width: 1000, height: 1000 };

      // 限制拖拽范围，确保宽高不小于最小值
      const minSize = 20;
      const maxX = group.x() + coord.width - minSize;
      const maxY = group.y() + coord.height - minSize;

      // 限制在舞台范围内
      const constrainedX = Math.max(
        stageBounds.x,
        Math.min(pos.x, Math.min(maxX, stageBounds.width - 10))
      );
      const constrainedY = Math.max(
        stageBounds.y,
        Math.min(pos.y, Math.min(maxY, stageBounds.height - 10))
      );

      return {
        x: constrainedX,
        y: constrainedY,
      };
    },
  });

  // 左上角水平线
  const topLeftHorizontal = new Konva.Line({
    points: [0, 0, lineLength, 0],
    stroke: opts.resizeHandleColor,
    strokeWidth: lineWidth,
    lineCap: "round",
  });

  // 左上角垂直线
  const topLeftVertical = new Konva.Line({
    points: [0, 0, 0, lineLength],
    stroke: opts.resizeHandleColor,
    strokeWidth: lineWidth,
    lineCap: "round",
  });

  // 左上角透明点击区域
  const topLeftClickArea = new Konva.Rect({
    x: -8,
    y: -8,
    width: lineLength + 8,
    height: lineLength + 8,
    fill: "transparent",
    listening: true,
  });

  topLeftHandle.add(topLeftHorizontal);
  topLeftHandle.add(topLeftVertical);
  topLeftHandle.add(topLeftClickArea);
  topLeftHandle.x(0);
  topLeftHandle.y(0);

  // 右上角控制点 (L型)
  const topRightHandle = new Konva.Group({
    draggable: true,
    dragBoundFunc: function (pos) {
      // 获取舞台边界
      const stage = this.getStage();
      const stageBounds = stage
        ? {
            x: 0,
            y: 0,
            width: stage.width(),
            height: stage.height(),
          }
        : { x: 0, y: 0, width: 1000, height: 1000 };

      const minSize = 20;
      const minX = group.x() + minSize;
      const maxY = group.y() + coord.height - minSize;

      // 限制在舞台范围内
      const constrainedX = Math.max(
        minX,
        Math.min(pos.x, stageBounds.width - 10)
      );
      const constrainedY = Math.max(
        stageBounds.y,
        Math.min(pos.y, Math.min(maxY, stageBounds.height - 10))
      );

      return {
        x: constrainedX,
        y: constrainedY,
      };
    },
  });

  // 右上角水平线
  const topRightHorizontal = new Konva.Line({
    points: [-lineLength, 0, 0, 0],
    stroke: opts.resizeHandleColor,
    strokeWidth: lineWidth,
    lineCap: "round",
  });

  // 右上角垂直线
  const topRightVertical = new Konva.Line({
    points: [0, 0, 0, lineLength],
    stroke: opts.resizeHandleColor,
    strokeWidth: lineWidth,
    lineCap: "round",
  });

  // 右上角透明点击区域
  const topRightClickArea = new Konva.Rect({
    x: -lineLength,
    y: -8,
    width: lineLength + 8,
    height: lineLength + 8,
    fill: "transparent",
    listening: true,
  });

  topRightHandle.add(topRightHorizontal);
  topRightHandle.add(topRightVertical);
  topRightHandle.add(topRightClickArea);
  topRightHandle.x(coord.width);
  topRightHandle.y(0);

  // 左下角控制点 (L型)
  const bottomLeftHandle = new Konva.Group({
    draggable: true,
    dragBoundFunc: function (pos) {
      // 获取舞台边界
      const stage = this.getStage();
      const stageBounds = stage
        ? {
            x: 0,
            y: 0,
            width: stage.width(),
            height: stage.height(),
          }
        : { x: 0, y: 0, width: 1000, height: 1000 };

      const minSize = 20;
      const maxX = group.x() + coord.width - minSize;
      const minY = group.y() + minSize;

      // 限制在舞台范围内
      const constrainedX = Math.max(
        stageBounds.x,
        Math.min(pos.x, Math.min(maxX, stageBounds.width - 10))
      );
      const constrainedY = Math.max(
        minY,
        Math.min(pos.y, stageBounds.height - 10)
      );

      return {
        x: constrainedX,
        y: constrainedY,
      };
    },
  });

  // 左下角水平线
  const bottomLeftHorizontal = new Konva.Line({
    points: [0, 0, lineLength, 0],
    stroke: opts.resizeHandleColor,
    strokeWidth: lineWidth,
    lineCap: "round",
  });

  // 左下角垂直线
  const bottomLeftVertical = new Konva.Line({
    points: [0, -lineLength, 0, 0],
    stroke: opts.resizeHandleColor,
    strokeWidth: lineWidth,
    lineCap: "round",
  });

  // 左下角透明点击区域
  const bottomLeftClickArea = new Konva.Rect({
    x: -8,
    y: -lineLength,
    width: lineLength + 8,
    height: lineLength + 8,
    fill: "transparent",
    listening: true,
  });

  bottomLeftHandle.add(bottomLeftHorizontal);
  bottomLeftHandle.add(bottomLeftVertical);
  bottomLeftHandle.add(bottomLeftClickArea);
  bottomLeftHandle.x(0);
  bottomLeftHandle.y(coord.height);

  // 右下角控制点 (L型)
  const bottomRightHandle = new Konva.Group({
    draggable: true,
    dragBoundFunc: function (pos) {
      // 获取舞台边界
      const stage = this.getStage();
      const stageBounds = stage
        ? {
            x: 0,
            y: 0,
            width: stage.width(),
            height: stage.height(),
          }
        : { x: 0, y: 0, width: 1000, height: 1000 };

      const minSize = 20;
      const minX = group.x() + minSize;
      const minY = group.y() + minSize;

      // 限制在舞台范围内
      const constrainedX = Math.max(
        minX,
        Math.min(pos.x, stageBounds.width - 10)
      );
      const constrainedY = Math.max(
        minY,
        Math.min(pos.y, stageBounds.height - 10)
      );
      
      return {
        x: constrainedX,
        y: constrainedY,
      };
    },
  });

  // 右下角水平线
  const bottomRightHorizontal = new Konva.Line({
    points: [-lineLength, 0, 0, 0],
    stroke: opts.resizeHandleColor,
    strokeWidth: lineWidth,
    lineCap: "round",
  });

  // 右下角垂直线
  const bottomRightVertical = new Konva.Line({
    points: [0, -lineLength, 0, 0],
    stroke: opts.resizeHandleColor,
    strokeWidth: lineWidth,
    lineCap: "round",
  });

  // 右下角透明点击区域
  const bottomRightClickArea = new Konva.Rect({
    x: -lineLength,
    y: -lineLength,
    width: lineLength + 8,
    height: lineLength + 8,
    fill: "transparent",
    listening: true,
  });

  bottomRightHandle.add(bottomRightHorizontal);
  bottomRightHandle.add(bottomRightVertical);
  bottomRightHandle.add(bottomRightClickArea);
  bottomRightHandle.x(coord.width);
  bottomRightHandle.y(coord.height);

  // 创建删除按钮组
  const deleteButtonGroup = new Konva.Group({
    x: coord.width,
    y: 0,
  });

  // 删除按钮背景
  const deleteBg = new Konva.Circle({
    x: 0,
    y: 0,
    radius: opts.deleteBtnSize / 2,
    fill: opts.deleteBtnColor,
  });

  // 删除按钮图标（×）
  const deleteIcon = new Konva.Text({
    x: 0,
    y: 0,
    text: "x",
    fontSize: 16,
    fontFamily: "Arial",
    fill: "#ffffff",
    align: "center",
    verticalAlign: "middle",
    offsetX: 4,
    offsetY: 8,
  });

  // 将背景和图标添加到删除按钮组
  deleteButtonGroup.add(deleteBg);
  deleteButtonGroup.add(deleteIcon);

  // 添加所有元素到组
  group.add(rect);
  group.add(topLeftHandle);
  group.add(topRightHandle);
  group.add(bottomLeftHandle);
  group.add(bottomRightHandle);
  group.add(deleteButtonGroup);

  // 存储引用，便于事件处理
  group.deleteButtonGroup = deleteButtonGroup;
  group.deleteButton = deleteBg;
  group.deleteIcon = deleteIcon;
  group.mainRect = rect;
  group.resizeHandles = {
    topLeft: topLeftHandle,
    topRight: topRightHandle,
    bottomLeft: bottomLeftHandle,
    bottomRight: bottomRightHandle,
  };

  // 初始时显示调整控制点
  group.resizeHandles.topLeft.visible(true);
  group.resizeHandles.topRight.visible(true);
  group.resizeHandles.bottomLeft.visible(true);
  group.resizeHandles.bottomRight.visible(true);

  return group;
}

/**
 * 显示/隐藏调整控制点
 * @param {Konva.Group} selectionBox - 框选框组
 * @param {boolean} visible - 是否显示
 */
export function toggleResizeHandles(selectionBox, visible) {
  if (!selectionBox || !selectionBox.resizeHandles) {
    return;
  }

  const handles = selectionBox.resizeHandles;
  handles.topLeft.visible(visible);
  handles.topRight.visible(visible);
  handles.bottomLeft.visible(visible);
  handles.bottomRight.visible(visible);

  const layer = selectionBox.getLayer();
  if (layer) {
    layer.batchDraw();
  }
}

/**
 * 更新框选框尺寸和控制点位置
 * @param {Konva.Group} selectionBox - 框选框组
 * @param {Object} newSize - 新的尺寸 {width, height}
 */
export function updateSelectionBoxSize(selectionBox, newSize) {
  if (!selectionBox || !selectionBox.mainRect || !selectionBox.resizeHandles) {
    return;
  }

  const { width, height } = newSize;
  const rect = selectionBox.mainRect;
  const handles = selectionBox.resizeHandles;
  const handleSize = 12;
  const halfHandle = handleSize / 2;
  const deleteBtnSize = 24;

  // 更新主矩形尺寸
  rect.width(width);
  rect.height(height);

  // 更新组的尺寸
  selectionBox.width(width);
  selectionBox.height(height);

  // 更新控制点位置
  handles.topLeft.x(0);
  handles.topLeft.y(0);

  handles.topRight.x(width);
  handles.topRight.y(0);

  handles.bottomLeft.x(0);
  handles.bottomLeft.y(height);

  handles.bottomRight.x(width);
  handles.bottomRight.y(height);

  // 更新删除按钮位置
  if (selectionBox.deleteButtonGroup) {
    selectionBox.deleteButtonGroup.x(width + deleteBtnSize / 4);
    selectionBox.deleteButtonGroup.y(-deleteBtnSize / 4);
  }

  const layer = selectionBox.getLayer();
  if (layer) {
    layer.batchDraw();
  }
}

/**
 * 约束框选框在图片范围内
 * @param {Konva.Group} selectionBox - 框选框组
 * @param {Object|Function} imageBounds - 图片边界对象或获取边界的函数
 */
export function constrainSelectionBox(selectionBox, imageBounds) {
  if (!selectionBox) {
    return;
  }
  
  // 支持动态获取imageBounds
  const currentBounds = typeof imageBounds === 'function' ? imageBounds() : imageBounds;
  
  if (!currentBounds) {
    return;
  }

  const box = selectionBox;
  const boxWidth = box.width();
  const boxHeight = box.height();

  let newX = box.x();
  let newY = box.y();

  // 限制在图片范围内
  newX = Math.max(
    currentBounds.x,
    Math.min(newX, currentBounds.x + currentBounds.width - boxWidth)
  );
  newY = Math.max(
    currentBounds.y,
    Math.min(newY, currentBounds.y + currentBounds.height - boxHeight)
  );

  box.x(newX);
  box.y(newY);
}

/**
 * 获取所有框选框的坐标数据
 * @param {Konva.Layer} selectionLayer - 框选框图层
 * @param {Object} imageBounds - 图片边界
 * @param {number} actualWidth - 图片实际宽度 (可选)
 * @param {number} actualHeight - 图片实际高度 (可选)
 * @returns {Array} 坐标数据数组
 */
export function getSelectionCoordinates(
  selectionLayer,
  imageBounds,
  actualWidth,
  actualHeight
) {
  if (!selectionLayer || !imageBounds) {
    return [];
  }

  const boxes = selectionLayer.find(".selection-box");

  return boxes.map((box) => {
    const absCoord = {
      x: box.x() - imageBounds.x,
      y: box.y() - imageBounds.y,
      width: box.width(),
      height: box.height(),
    };

    // 转换为相对坐标
    // 计算显示尺寸与实际尺寸的比例
    const scaleX = imageBounds.width / actualWidth;
    const scaleY = imageBounds.height / actualHeight;

    return {
      id: box.id(),
      x: absCoord.x / scaleX,
      y: absCoord.y / scaleY,
      width: absCoord.width / scaleX,
      height: absCoord.height / scaleY,
    };
  });
}

/**
 * 清空图层
 * @param {Konva.Layer} layer - 要清空的图层
 */
export function clearLayer(layer) {
  if (!layer) {
    return;
  }

  layer.removeChildren();
  layer.batchDraw();
}

/**
 * 添加框选框拖拽事件
 * @param {Konva.Group} selectionBox - 框选框组
 * @param {Object|Function} imageBounds - 图片边界对象或获取边界的函数
 * @param {Function} onDragStart - 拖拽开始回调
 * @param {Function} onDragEnd - 拖拽结束回调
 * @param {Function} onResize - 调整大小回调
 * @param {Function} onDragMove - 拖拽移动回调（可选）
 */
export function addSelectionBoxEvents(
  selectionBox,
  imageBounds,
  onDragStart,
  onDragEnd,
  onResize,
  onDragMove
) {
  // 主框选框拖拽事件
  selectionBox.on("dragstart", () => {
    toggleResizeHandles(selectionBox, true); // 拖拽时保持控制点显示
    if (onDragStart) onDragStart(selectionBox);
  });

  selectionBox.on("dragmove", () => {
    // 支持动态获取imageBounds
    const currentBounds = typeof imageBounds === 'function' ? imageBounds() : imageBounds;
    constrainSelectionBox(selectionBox, currentBounds);
    if (onDragMove) onDragMove(selectionBox);
  });

  selectionBox.on("dragend", () => {
    if (onDragEnd) onDragEnd(selectionBox);
  });

  // 点击框选框时保持所有控制点显示
  selectionBox.on("click tap", (e) => {
    // 如果点击的是控制点或删除按钮，不处理
    if (
      e.target === selectionBox.deleteButton ||
      e.target === selectionBox.deleteIcon ||
      Object.values(selectionBox.resizeHandles).includes(e.target)
    ) {
      return;
    }

    // 保持所有框选框的控制点显示
    const layer = selectionBox.getLayer();
    if (layer) {
      const allBoxes = layer.find(".selection-box");
      allBoxes.forEach((box) => {
        toggleResizeHandles(box, true);
      });
    }
  });

  // 添加调整大小事件处理
  addResizeEvents(selectionBox, imageBounds, onResize, onDragMove);

  // 删除按钮点击事件
  selectionBox.deleteButton.on("click tap", (e) => {
    e.cancelBubble = true;
    const layer = selectionBox.getLayer();
    selectionBox.destroy();
    if (layer) {
      layer.batchDraw();
    }
  });

  selectionBox.deleteIcon.on("click tap", (e) => {
    e.cancelBubble = true;
    const layer = selectionBox.getLayer();
    selectionBox.destroy();
    if (layer) {
      layer.batchDraw();
    }
  });
}

/**
 * 添加调整大小事件处理
 * @param {Konva.Group} selectionBox - 框选框组
 * @param {Object|Function} imageBounds - 图片边界对象或获取边界的函数
 * @param {Function} onResize - 调整大小回调
 * @param {Function} onResizeMove - 调整大小移动回调（可选）
 */
function addResizeEvents(selectionBox, imageBounds, onResize, onResizeMove) {
  const handles = selectionBox.resizeHandles;

  // 左上角控制点
  handles.topLeft.on("dragmove", () => {
    const pos = handles.topLeft.position();
    const groupPos = selectionBox.position();
    const currentWidth = selectionBox.width();
    const currentHeight = selectionBox.height();

    // 计算理论上的新位置和尺寸
    const theoreticalNewX = groupPos.x + pos.x;
    const theoreticalNewY = groupPos.y + pos.y;
    const theoreticalNewWidth = currentWidth - pos.x;
    const theoreticalNewHeight = currentHeight - pos.y;

    // 限制最小尺寸和边界
    const minSize = 20;
    
    // 支持动态获取imageBounds
    const currentBounds = typeof imageBounds === 'function' ? imageBounds() : imageBounds;

    // 约束新位置在合理范围内
    const constrainedNewX = Math.max(
      currentBounds.x,
      Math.min(theoreticalNewX, currentBounds.x + currentBounds.width - minSize)
    );
    const constrainedNewY = Math.max(
      currentBounds.y,
      Math.min(theoreticalNewY, currentBounds.y + currentBounds.height - minSize)
    );

    // 基于约束后的位置重新计算尺寸
    const actualNewWidth = Math.max(
      minSize,
      groupPos.x + currentWidth - constrainedNewX
    );
    const actualNewHeight = Math.max(
      minSize,
      groupPos.y + currentHeight - constrainedNewY
    );

    // 应用约束后的结果
    selectionBox.x(constrainedNewX);
    selectionBox.y(constrainedNewY);
    updateSelectionBoxSize(selectionBox, {
      width: actualNewWidth,
      height: actualNewHeight,
    });

    // 重置控制点位置
    handles.topLeft.x(0);
    handles.topLeft.y(0);

    // 触发实时更新回调
    if (onResizeMove) onResizeMove(selectionBox);
  });

  // 右上角控制点
  handles.topRight.on("dragmove", () => {
    const pos = handles.topRight.position();
    const groupPos = selectionBox.position();
    const currentHeight = selectionBox.height();

    // 计算理论上的新位置和尺寸
    const theoreticalNewWidth = pos.x;
    const theoreticalNewY = groupPos.y + pos.y;
    const theoreticalNewHeight = currentHeight - pos.y;

    // 限制最小尺寸和边界
    const minSize = 20;
    
    // 支持动态获取imageBounds
    const currentBounds = typeof imageBounds === 'function' ? imageBounds() : imageBounds;

    // 约束新位置和尺寸在合理范围内
    const constrainedNewY = Math.max(
      currentBounds.y,
      Math.min(theoreticalNewY, currentBounds.y + currentBounds.height - minSize)
    );
    const constrainedWidth = Math.max(
      minSize,
      Math.min(
        theoreticalNewWidth,
        currentBounds.x + currentBounds.width - groupPos.x
      )
    );

    // 基于约束后的位置重新计算高度
    const actualNewHeight = Math.max(
      minSize,
      groupPos.y + currentHeight - constrainedNewY
    );

    // 应用约束后的结果
    selectionBox.y(constrainedNewY);
    updateSelectionBoxSize(selectionBox, {
      width: constrainedWidth,
      height: actualNewHeight,
    });

    handles.topRight.x(constrainedWidth);
    handles.topRight.y(0);

    // 触发实时更新回调
    if (onResizeMove) onResizeMove(selectionBox);
  });

  // 左下角控制点
  handles.bottomLeft.on("dragmove", () => {
    const pos = handles.bottomLeft.position();
    const groupPos = selectionBox.position();
    const currentWidth = selectionBox.width();

    // 计算理论上的新位置和尺寸
    const theoreticalNewX = groupPos.x + pos.x;
    const theoreticalNewWidth = currentWidth - pos.x;
    const theoreticalNewHeight = pos.y;

    // 限制最小尺寸和边界
    const minSize = 20;
    
    // 支持动态获取imageBounds
    const currentBounds = typeof imageBounds === 'function' ? imageBounds() : imageBounds;

    // 约束新位置在合理范围内
    const constrainedNewX = Math.max(
      currentBounds.x,
      Math.min(theoreticalNewX, currentBounds.x + currentBounds.width - minSize)
    );
    const constrainedHeight = Math.max(
      minSize,
      Math.min(
        theoreticalNewHeight,
        currentBounds.y + currentBounds.height - groupPos.y
      )
    );

    // 基于约束后的位置重新计算宽度
    const actualNewWidth = Math.max(
      minSize,
      groupPos.x + currentWidth - constrainedNewX
    );

    // 应用约束后的结果
    selectionBox.x(constrainedNewX);
    updateSelectionBoxSize(selectionBox, {
      width: actualNewWidth,
      height: constrainedHeight,
    });

    handles.bottomLeft.x(0);
    handles.bottomLeft.y(constrainedHeight);

    // 触发实时更新回调
    if (onResizeMove) onResizeMove(selectionBox);
  });

  // 右下角控制点
  handles.bottomRight.on("dragmove", () => {
    const pos = handles.bottomRight.position();
    const groupPos = selectionBox.position();

    // 计算理论上的新尺寸
    const theoreticalNewWidth = pos.x;
    const theoreticalNewHeight = pos.y;

    // 限制最小尺寸和边界
    const minSize = 20;
    
    // 支持动态获取imageBounds
    const currentBounds = typeof imageBounds === 'function' ? imageBounds() : imageBounds;

    // 约束尺寸在合理范围内
    const constrainedWidth = Math.max(
      minSize,
      Math.min(
        theoreticalNewWidth,
        currentBounds.x + currentBounds.width - groupPos.x
      )
    );
    const constrainedHeight = Math.max(
      minSize,
      Math.min(
        theoreticalNewHeight,
        currentBounds.y + currentBounds.height - groupPos.y
      )
    );

    // 应用约束后的结果
    updateSelectionBoxSize(selectionBox, {
      width: constrainedWidth,
      height: constrainedHeight,
    });

    handles.bottomRight.x(constrainedWidth);
    handles.bottomRight.y(constrainedHeight);

    // 触发实时更新回调
    if (onResizeMove) onResizeMove(selectionBox);
  });

  // 调整大小结束事件
  Object.values(handles).forEach((handle) => {
    handle.on("dragend", () => {
      if (onResize) onResize(selectionBox);
    });
  });
}

/**
 * 创建截图遮罩效果
 * @param {Konva.Layer} maskLayer - 遮罩图层
 * @param {Object} stageBounds - 舞台边界 {width, height}
 * @param {Object} imageBounds - 图片边界 {x, y, width, height}
 * @param {Array} selectionBoxes - 框选框数组
 */
export function createScreenshotMask(
  maskLayer,
  stageBounds,
  imageBounds,
  selectionBoxes
) {
  // 清空遮罩层
  clearLayer(maskLayer);

  if (selectionBoxes.length === 0) {
    // 没有框选框时，创建全屏遮罩
    const fullMask = new Konva.Rect({
      x: 0,
      y: 0,
      width: stageBounds.width,
      height: stageBounds.height,
      fill: "rgba(0, 0, 0, 0.6)",
      listening: false,
    });
    maskLayer.add(fullMask);
  } else {
    // 有框选框时，创建带裁剪的遮罩

    // 构建SVG路径字符串，用于创建带洞的遮罩
    let pathData = `M 0 0 L ${stageBounds.width} 0 L ${stageBounds.width} ${stageBounds.height} L 0 ${stageBounds.height} Z`;

    // 为每个框选框添加洞（逆时针方向）
    selectionBoxes.forEach((box) => {
      const x = box.x();
      const y = box.y();
      const w = box.width();
      const h = box.height();

      // 添加矩形洞（逆时针绘制以创建洞）
      pathData += ` M ${x} ${y} L ${x} ${y + h} L ${x + w} ${y + h} L ${
        x + w
      } ${y} Z`;
    });

    // 创建带洞的路径
    const maskPath = new Konva.Path({
      data: pathData,
      fill: "rgba(0, 0, 0, 0.6)",
      fillRule: "evenodd", // 使用evenodd规则来处理洞
      listening: false,
    });

    maskLayer.add(maskPath);
  }

  maskLayer.batchDraw();
}

/**
 * 更新截图遮罩
 * @param {Konva.Layer} maskLayer - 遮罩图层
 * @param {Konva.Layer} selectionLayer - 框选框图层
 * @param {Object} stageBounds - 舞台边界
 * @param {Object} imageBounds - 图片边界
 * @param {number} rotation - 旋转角度 (可选)
 */
export function updateScreenshotMask(
  maskLayer,
  selectionLayer,
  stageBounds,
  imageBounds,
  rotation = 0
) {
  if (!maskLayer || !selectionLayer) return;

  // 获取所有框选框
  const selectionBoxes = selectionLayer.find(".selection-box");

  // 重新创建遮罩
  createScreenshotMask(maskLayer, stageBounds, imageBounds, selectionBoxes);
}

/**
 * 创建旋转状态下的遮罩
 * @param {Konva.Layer} maskLayer - 遮罩图层
 * @param {Object} stageBounds - 舞台边界
 * @param {Object} imageBounds - 图片边界
 * @param {number} rotation - 旋转角度
 */
export function createRotatedMask(
  maskLayer,
  stageBounds,
  imageBounds,
  rotation
) {
  if (!maskLayer) return;

  // 清空遮罩层
  clearLayer(maskLayer);

  // 创建全屏半透明遮罩（背景）
  const fullMask = new Konva.Rect({
    x: 0,
    y: 0,
    width: stageBounds.width,
    height: stageBounds.height,
    fill: "rgba(0, 0, 0, 0.6)",
    listening: false,
  });

  // 计算旋转中心点
  const centerX = imageBounds.x + imageBounds.width / 2;
  const centerY = imageBounds.y + imageBounds.height / 2;

  // 先从全屏遮罩上抠出图片区域（使图片区域透明）
  const rotatedClearHole = new Konva.Rect({
    x: imageBounds.x,
    y: imageBounds.y,
    width: imageBounds.width,
    height: imageBounds.height,
    fill: "rgba(0,0,0,1)",
    listening: false,
    offsetX: imageBounds.width / 2,
    offsetY: imageBounds.height / 2,
    x: centerX,
    y: centerY,
    rotation: rotation,
  });
  rotatedClearHole.globalCompositeOperation("destination-out");

  // 在抠出区域内再叠加一层较浅的遮罩（与框选框效果一致）
  const rotatedInnerOverlay = new Konva.Rect({
    x: imageBounds.x,
    y: imageBounds.y,
    width: imageBounds.width,
    height: imageBounds.height,
    fill: "rgba(0, 0, 0, 0.3)",
    listening: false,
    offsetX: imageBounds.width / 2,
    offsetY: imageBounds.height / 2,
    x: centerX,
    y: centerY,
    rotation: rotation,
  });

  // 图片区域边框（虚线）
  const rotatedBorder = new Konva.Rect({
    x: imageBounds.x,
    y: imageBounds.y,
    width: imageBounds.width,
    height: imageBounds.height,
    stroke: "rgba(255, 255, 255, 0.5)",
    strokeWidth: 2,
    dash: [5, 5],
    listening: false,
    offsetX: imageBounds.width / 2,
    offsetY: imageBounds.height / 2,
    x: centerX,
    y: centerY,
    rotation: rotation,
  });

  maskLayer.add(fullMask);
  maskLayer.add(rotatedClearHole);
  maskLayer.add(rotatedInnerOverlay);
  maskLayer.add(rotatedBorder);
  maskLayer.batchDraw();
}

/**
 * 销毁舞台
 * @param {Konva.Stage} stage - 要销毁的舞台
 */
export function destroyStage(stage) {
  if (stage) {
    stage.destroy();
  }
}
